#include <stdio.h>
#include <string.h>
#include <stdlib.h>

enum program_options{ FASE1 = 1, FASE2 = 2, FASE3 = 3, FASE4 = 4 };
typedef unsigned int   ui32;
typedef unsigned short ui16;
typedef unsigned char  ui8;


//#################################################################
//                      <header.h>
//#################################################################
typedef struct object_header{
	ui16 Machine;
	ui16 NumberOfSections;
	ui32 TimeDateStamp;
	ui32 PointerToSymbolTable;
	ui32 NumberOfSymbols;
	ui16 SizeOfOptionalHeader;
	ui16 Characteristics;
}object_header_t;


void object_header_free( object_header_t *h );
object_header_t * object_header_load( FILE * fp );

ui8 * object_header_to_string( object_header_t *h );
ui8 * object_header_to_xml_string( object_header_t *h );
void object_header_to_string_free( ui8 * c );

ui32 object_header_section_table_position(object_header_t *h);
ui32 object_header_symbol_table_position(object_header_t *h);

ui32 object_header_string_table_position(object_header_t *h);
//#################################################################
//                      </header.h>
//#################################################################


//#################################################################
//                      <section.h>
//#################################################################
typedef struct object_relocations{
	ui32 VirtualAddress;
	ui32 SymbolTableIndex;
	ui16 Type;
}object_relocations_t;

typedef struct object_section{
	ui8  Name[8];
	ui32   VirtualSize;
	ui32   VirtualAddress;
    ui32   SizeOfRawData;
	ui32   PointerToRawData;
	ui32   PointerToRelocations;
	ui32   PointerToLinenumbers;
	ui16 NumberOfRelocations;
	ui16 NumberOfLinenumbers;
	ui32   Characteristics;
}object_section_t;

void object_section_free( object_section_t **s, object_header_t *oh);
object_section_t ** object_section_load( FILE *fp, object_header_t *oh );

ui32 object_section_relocations_table_position(object_section_t *s);

ui8 * object_section_to_string( object_section_t *s );
ui8 * object_section_to_xml_string( object_section_t *s );
void object_section_to_string_free( ui8 * c );

object_section_t* object_section_get_text_section(object_section_t **sections, object_header_t *oh );
//#################################################################
//                      </section.h>
//#################################################################


//#################################################################
//                      <symbol.h>
//#################################################################
typedef struct object_symbol{
	union {
		ui8 Name[8];
		struct {
			ui32 Zeroes;
			ui32 Offset;
		} lname;
	} sname;
	ui32   Value;
	ui16 SectionNumber;
	ui16 Type;
	ui8  StorageClass;
	ui8  NumberOfAuxSymbols;
}object_symbol_t;

ui8 * object_symbol_to_string( object_symbol_t *s );
ui8 * object_symbol_to_xml_string( object_symbol_t *s );
void object_symbol_to_string_free( ui8 * c );

void object_symbol_free( object_symbol_t **s, object_header_t *oh);
object_symbol_t ** object_symbol_load( FILE *fp, object_header_t *oh );

ui32 symbol_get_section_id( object_header_t *oh, object_section_t *sections, object_symbol_t **s );

ui8* symbol_get_real_name( FILE *fp, object_header_t *oh, object_symbol_t *s );
void symbol_get_real_name_with_buffer( FILE *fp, object_header_t *oh, object_symbol_t *s, ui8* buffer );

ui8* symbol_get_storageclass_description(object_symbol_t *s);

void symbol_set(FILE *fp, object_header_t *oh, object_symbol_t *s, ui32 index);
//#################################################################
//                      </symbol.h>
//#################################################################


//#################################################################
//                      <relocations.h>
//#################################################################
void object_relocations_free( object_relocations_t **r, object_section_t *s );
object_relocations_t **object_relocations_load( FILE * fp, object_section_t *s );

ui8 * object_relocations_to_string( object_relocations_t *s );
ui8 * object_relocations_to_xml_string( object_relocations_t *s );
void object_relocations_to_string_free( ui8 * c );
//#################################################################
//                      </relocations.h>
//#################################################################


//#################################################################
//                      <xml.h>
//#################################################################
ui8 * xml_parse_element( ui8 *p );
//#################################################################
//                      </xml.h>
//#################################################################


//#################################################################
//                      <dumpcls.h>
//#################################################################
void dump_cls_constructor();
void dump_cls_destructor();

void do_option_1();
void do_option_2(ui8 *fn);
void do_option_3( ui8 *osymbol, ui8 *dsymbol);
void do_option_4( ui32 argc, ui32 option_index, ui8 **argv );

void dumpcls_show_header();
void dumpcls_show_symbol();
void dumpcls_show_section();
void dumpcls_close_header();
//#################################################################
//                      </dumpcls.h>
//#################################################################


//#################################################################
//                      <string table.h>
//#################################################################
ui8 * string_table_load_string( FILE *fp, object_header_t *h, ui32 offset );

ui32 string_table_get_lenght(FILE *fp, object_header_t *h);
ui32 string_table_add_string(FILE *fp, object_header_t *h, ui8 *s);
//#################################################################
//                      </string table.h>
//#################################################################

